package com.ec50n9.server.module.issue

import cn.dev33.satoken.stp.StpUtil
import com.ec50n9.server.common.SpringUtils
import com.ec50n9.server.module.comment.Comment
import com.ec50n9.server.module.comment.CommentListRendered
import com.ec50n9.server.module.common.*
import com.ec50n9.server.module.issueCategory.IssueCategory
import com.ec50n9.server.module.issueCategory.IssueCategoryQueryRendered
import com.ec50n9.server.module.issueCategory.IssueCategoryService
import com.ec50n9.server.module.user.User
import com.ec50n9.server.module.user.UserQueryRendered
import com.ec50n9.server.module.user.UserService
import org.hibernate.annotations.GenericGenerator
import java.time.LocalDateTime
import javax.persistence.*
import javax.validation.constraints.NotBlank

@Entity
class Issue(
    var title: String,
    var content: String,
    @ManyToOne var category: IssueCategory,
    @ManyToOne var author: User?,
    @OneToMany var comments: MutableList<Comment> = mutableListOf(),
    var launchedAt: LocalDateTime = LocalDateTime.now(),
    var contactWay: String? = null,
    var contactNumber: String? = null,
    var voteCount: Int = 0,

    @Id
    @GenericGenerator(name = "nanoid", strategy = "com.ec50n9.server.common.NanoIdGenerator")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "nanoid")
    var id: String? = null
) : Render<Issue>()

/**
 * 创建表单
 */
data class IssueCreateForm(
    @field:NotBlank(message = "标题不能为空")
    var title: String? = null,
    @field:NotBlank(message = "内容不能为空")
    var content: String? = null,
    @field:NotBlank(message = "分类不能为空")
    var categoryId: String? = null,
    @field:NotBlank(message = "联系方式不能为空")
    var contactWay: String? = null,
    @field:NotBlank(message = "联系号码不能为空")
    var contactNumber: String? = null,
) : CreateForm<Issue> {
    override fun renderTo(): Issue {
        val categoryService = SpringUtils.getBean(IssueCategoryService::class.java)
        val userService = SpringUtils.getBean(UserService::class.java)
        val category = categoryService.findOne(categoryId!!)
        val author = userService.findOneByUsername(StpUtil.getLoginIdAsString())
        return Issue(
            title!!, content!!, category, author,
            contactWay = contactWay, contactNumber = contactNumber
        )
    }
}

/**
 * 更新表单
 */
data class IssueUpdateForm(
    var title: String? = null,
    var content: String? = null,
    var categoryId: String? = null,
    var contactWay: String? = null,
    var contactNumber: String? = null,
    var voteCount: Int? = null,
) : UpdateForm<Issue> {
    override fun renderTo(target: Issue) {
        val categoryService = SpringUtils.getBean(IssueCategoryService::class.java)

        title?.let { target.title = it }
        content?.let { target.content = it }
        categoryId?.let {
            val category = categoryService.findOne(it)
            target.category = category
        }
        contactWay?.let { target.contactWay = it }
        contactNumber?.let { target.contactNumber = it }
        voteCount?.let { target.voteCount = it }
    }
}

/**
 * 列表渲染
 */
data class IssueListRendered(
    var id: String? = null,
    var title: String? = null,
    var content: String? = null,
    var categoryName: String? = null,
    var authorName: String? = null,
    var launchedAt: LocalDateTime? = null,
    var contactWay: String? = null,
    var contactNumber: String? = null,
    var voteCount: Int = 0,
    var commentCount: Int = 0,
) : Rendered<Issue> {
    override fun renderFrom(from: Issue) {
        id = from.id
        title = from.title
        content = from.content
        categoryName = from.category.name
        authorName = from.author?.nickname
        launchedAt = from.launchedAt
        contactWay = from.contactWay
        contactNumber = from.contactNumber
        voteCount = from.voteCount
        commentCount = from.comments.size
    }
}

/**
 * 查询渲染
 */
data class IssueDetailRendered(
    var id: String? = null,
    var title: String? = null,
    var content: String? = null,
    var category: IssueCategoryQueryRendered? = null,
    var author: UserQueryRendered? = null,
    var comments: List<CommentListRendered>? = listOf(),
    var launchedAt: LocalDateTime? = null,
    var contactWay: String? = null,
    var contactNumber: String? = null,
    var voteCount: Int = 0,
    var commentCount: Int = 0,
) : Rendered<Issue> {
    override fun renderFrom(from: Issue) {
        id = from.id
        title = from.title
        content = from.content
        category = from.category.renderTo(IssueCategoryQueryRendered::class.java)
        author = from.author?.renderTo(UserQueryRendered::class.java)
        comments = from.comments.renderTo(CommentListRendered::class.java)
        launchedAt = from.launchedAt
        contactWay = from.contactWay
        contactNumber = from.contactNumber
        voteCount = from.voteCount
        commentCount = from.comments.size
    }
}